﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing.Imaging;
using System.Drawing;
using System.ComponentModel;

namespace Common.Drawing
{
    public static class BitmapImageHelper
    {
        private const int RGBMax = 3;
        private const int MagicPixelPaddingCode = 255;

        /// <summary>
        /// Gets the RGB pixels of a bitmap image as bytes.
        /// </summary>
        /// <param name="strFilePath">File name to a bitmap.</param>
        /// <returns>RGB as byte array. Ex: One pixel equals three bytes.</returns>
        public static byte[] GetARGB(string strFilePath)
        {
            if (String.IsNullOrEmpty(strFilePath)) return null;

            Bitmap bit = new Bitmap(strFilePath);
            Color curclr;
            byte[] RawData = new byte[(bit.Height * bit.Width) * RGBMax];

            for (int y = 0; y < bit.Height; y++)
            {
                for (int x = 0; x < bit.Width; x++)
                {
                    curclr = bit.GetPixel(x, y);
                    RawData[(x + (y * bit.Width)) * RGBMax + 0] = curclr.R;
                    RawData[(x + (y * bit.Width)) * RGBMax + 1] = curclr.G;
                    RawData[(x + (y * bit.Width)) * RGBMax + 2] = curclr.B;
                }
            }



            // Removes Magic Pixel Padding from the end of array.
            return RawData.Reverse()
                          .SkipWhile(
                                      p =>
                                          p == MagicPixelPaddingCode.ToByte()
                                    ).Reverse()
                                     .ToArray<byte>();
        }

        /// <summary>
        /// Converts a byte array to a bitmap. Ex: Three bytes will equal one pixel.
        /// Adds padding to the end, if byte array is not a even factor of three.
        /// </summary>
        /// <param name="RawData">Data to be converted to a RGB pixel.</param>
        /// <returns>Bitmap of the data.</returns>
        public static Bitmap SetARGB(byte[] RawData)
        {
            if (RawData.isNull() || RawData.Length < 1) return null;
            int iTotalPixels = RawData.Length / RGBMax;
            int w = Math.Ceiling(Math.Sqrt(iTotalPixels)).ToInt();
            int h = Math.Ceiling(Math.Sqrt(iTotalPixels)).ToInt();
            Bitmap bit = new Bitmap(w, h);
            int[] iRGB = new int[3];

            for (int y = 0; y < bit.Height; y++)
            {
                for (int x = 0; x < bit.Width; x++)
                {
                    iRGB.SetValue(MagicPixelPaddingCode, 0, 1, 2);

                    try
                    {
                        iRGB[0] = RawData[(x + (y * bit.Width)) * RGBMax + 0];
                        iRGB[1] = RawData[(x + (y * bit.Width)) * RGBMax + 1];
                        iRGB[2] = RawData[(x + (y * bit.Width)) * RGBMax + 2];
                    }
                    catch (IndexOutOfRangeException)
                    {
                    }

                    bit.SetPixel(x, y, Color.FromArgb(iRGB[0], iRGB[1], iRGB[2]));
                }
            }

            return bit;
        }
    }
}
